﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using YArchitech.LIB;
using YArchitech.Public;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	public class HYDuctConnectUtil
	{
		public int BatchConnTerminalByFitting(Duct mainDuct, IList<FamilyInstance> terminals, XYZ globalPoint, int ductConnType, int terminalConnType, int alignType)
		{
			int result = 0;
			try
			{
				Connector connector = null;
				Connector connector2 = null;
				this.GetConnectors(mainDuct, globalPoint, ref connector, ref connector2);
				if (connector == null || connector2 == null)
				{
					return result;
				}
				XYZ origin = connector.Origin;
				IList<FamilyInstance> list = this.FilterTerminals(mainDuct, terminals, connector, connector2);
				int num = this.ConnectEndOfDuct(list, mainDuct, origin, terminalConnType, alignType);
				if (list.Count <= 0)
				{
					result = num;
					return result;
				}
				IDictionary<double, List<FamilyInstance>> dictionary = this.OrderTerminals(mainDuct, list, origin);
				IList<FamilyInstance> toBeRemovedItems;
				IDictionary<double, Dictionary<FamilyInstance, int>> coveredTerminals = this.GetCoveredTerminals(mainDuct, dictionary, out toBeRemovedItems);
				IList<Duct> splitDucts;
				int num2 = this.ConnectCoveredTerminalsByFitting(mainDuct, coveredTerminals, origin, terminalConnType, alignType, out splitDucts);
				IDictionary<double, List<FamilyInstance>> orderTerminals = this.RemoveInvalidItems(dictionary, toBeRemovedItems);
				IList<FamilyInstance> list2;
				IEnumerable<KeyValuePair<Duct, List<FamilyInstance>>> enumerable = this.GroupDuctAndTerminal(splitDucts, orderTerminals, origin, out list2);
				HYDuctConnect hyductConnect = new HYDuctConnect();
				Duct duct = null;
				int num3 = 0;
				foreach (KeyValuePair<Duct, List<FamilyInstance>> keyValuePair in enumerable)
				{
					duct = keyValuePair.Key;
					List<FamilyInstance> value = keyValuePair.Value;
					if (hyductConnect.DuctConnectAirTerminalByRectangleN(ref duct, value.ToList<Element>(), ductConnType, terminalConnType, origin, alignType))
					{
						num3 += value.Count;
					}
				}
				result = num + num2 + num3;
			}
			catch (Exception)
			{
			}
			return result;
		}

		private int ConnectEndOfDuct(IList<FamilyInstance> terminals, Duct duct, XYZ entrancePnt, int terminalConnType, int alignType)
		{
			int result = 0;
			if (duct == null || terminals == null || terminals.Count <= 0)
			{
				return result;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			Connector closeConnector = hypiping.GetCloseConnector(entrancePnt, false);
			Connector closeConnector2 = hypiping.GetCloseConnector(entrancePnt, true);
			IList<FamilyInstance> list;
			if (this.CheckProjectionInExtDuct(terminals, closeConnector, closeConnector2, out list))
			{
				bool flag;
				result = this.ConnectFarthestTerminals(list, duct, terminalConnType, alignType, out flag);
				if (!flag)
				{
					return result;
				}
				IEnumerator<FamilyInstance> enumerator = list.GetEnumerator();
				{
					while (enumerator.MoveNext())
					{
						FamilyInstance item = enumerator.Current;
						terminals.Remove(item);
					}
					return result;
				}
			}
			IList<FamilyInstance> list2;
			if (this.CheckTerminalInDuctTerminal(terminals, duct, closeConnector, closeConnector2, out list, out list2))
			{
				if (list != null && list.Count > 0)
				{
					bool flag;
					result = this.ConnectFarthestTerminals(list, duct, terminalConnType, alignType, out flag);
					if (!flag)
					{
						return result;
					}
					IEnumerator<FamilyInstance> enumerator = list.GetEnumerator();
					{
						while (enumerator.MoveNext())
						{
							FamilyInstance item2 = enumerator.Current;
							terminals.Remove(item2);
						}
						return result;
					}
				}
				if (list2 != null && list2.Count > 0)
				{
					bool flag;
					result = this.ConnectFarthestTerminals(list2, duct, terminalConnType, alignType, out flag);
					if (flag)
					{
						foreach (FamilyInstance item3 in list2)
						{
							terminals.Remove(item3);
						}
					}
				}
			}
			return result;
		}

		private bool CheckTerminalInDuctTerminal(IList<FamilyInstance> terminals, Duct duct, Connector sConnector, Connector eConnector, out IList<FamilyInstance> startNearTerminals, out IList<FamilyInstance> endNearTerminals)
		{
			startNearTerminals = new List<FamilyInstance>();
			endNearTerminals = new List<FamilyInstance>();
			double num = YJKRevitTools.GetDuctWidthorDiameter(duct);
			YJKLine hyline = new YJKLine(sConnector.Origin, eConnector.Origin);
			hyline.MakeUnBound();
			foreach (FamilyInstance familyInstance in terminals)
			{
				XYZ point = (familyInstance.Location as LocationPoint).Point;
				double num2 = hyline.GetProject(point).DistanceTo(sConnector.Origin);
				if (num2 < num)
				{
					num = num2;
					startNearTerminals.Clear();
					startNearTerminals.Add(familyInstance);
				}
				else if (num2 == num)
				{
					startNearTerminals.Add(familyInstance);
				}
			}
			foreach (FamilyInstance familyInstance2 in terminals)
			{
				XYZ point = (familyInstance2.Location as LocationPoint).Point;
				double num2 = hyline.GetProject(point).DistanceTo(eConnector.Origin);
				if (num2 < num)
				{
					num = num2;
					endNearTerminals.Clear();
					endNearTerminals.Add(familyInstance2);
				}
				else if (num2 == num)
				{
					endNearTerminals.Add(familyInstance2);
				}
			}
			return startNearTerminals.Count > 0 || endNearTerminals.Count > 0;
		}

		public int BatchConnTerminalByJoint(Duct duct, IList<FamilyInstance> terminals, int terminalConnType, int alignType)
		{
			int num = 0;
			try
			{
				HYDuctConnect hyductConnect = new HYDuctConnect();
				foreach (FamilyInstance familyInstance in terminals)
				{
					Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, familyInstance);
					if (elementConnector != null && !elementConnector.IsConnected)
					{
						int connType = -1;
						if (string.IsNullOrEmpty(hyductConnect.CheckTerminalBeCovered(duct, familyInstance, ref connType, true)) && this.ConnectCoveredTerminalByJoint(duct, familyInstance, connType, terminalConnType, alignType))
						{
							num++;
						}
					}
				}
			}
			catch (Exception)
			{
				num = 0;
			}
			return num;
		}

		public bool ConnectCoveredTerminalByJoint(Duct duct, FamilyInstance terminal, int connType, int terminalConnType, int alignType)
		{
			if (duct == null || terminal == null)
			{
				return false;
			}
			bool result = false;
			string empty = string.Empty;
			bool beFlex = terminalConnType == 1;
			try
			{
				if (connType != 22)
				{
					if (connType == 33)
					{
						result = this.DirectConnectTerminal(duct, terminal, ref empty, beFlex);
					}
				}
				else
				{
					result = this.DirectSideConnectTerminal(duct, terminal, connType, alignType, ref empty, beFlex);
				}
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private IDictionary<Duct, List<FamilyInstance>> GroupDuctAndTerminal(IList<Duct> splitDucts, IDictionary<double, List<FamilyInstance>> orderTerminals, XYZ entrancePnt, out IList<FamilyInstance> notMatchedList)
		{
			notMatchedList = new List<FamilyInstance>();
			if (splitDucts == null || orderTerminals == null)
			{
				return null;
			}
			IDictionary<Duct, List<FamilyInstance>> dictionary = new Dictionary<Duct, List<FamilyInstance>>();
			new List<FamilyInstance>();
			List<FamilyInstance> list = null;
			List<FamilyInstance> list2 = new List<FamilyInstance>();
			foreach (KeyValuePair<double, List<FamilyInstance>> keyValuePair in orderTerminals)
			{
				list2.AddRange(keyValuePair.Value);
			}
			foreach (Duct duct in splitDucts)
			{
				list = new List<FamilyInstance>();
				foreach (FamilyInstance familyInstance in list2)
				{
					bool flag = this.IsValidDirection(duct, familyInstance, entrancePnt);
					bool flag2 = this.IsValidDistance(duct, familyInstance);
					if (flag && flag2)
					{
						list.Add(familyInstance);
					}
					else if (!flag2)
					{
						notMatchedList.Add(familyInstance);
					}
				}
				if (list.Count > 0)
				{
					dictionary.Add(duct, list);
					foreach (FamilyInstance item in list)
					{
						list2.Remove(item);
					}
					foreach (FamilyInstance item2 in notMatchedList)
					{
						list2.Remove(item2);
					}
				}
			}
			return dictionary;
		}

		private bool IsValidDirection(Duct duct, FamilyInstance terminal, XYZ entrancePnt)
		{
			if (duct == null || terminal == null)
			{
				return false;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			Connector closeConnector = hypiping.GetCloseConnector(entrancePnt, false);
			Connector closeConnector2 = hypiping.GetCloseConnector(entrancePnt, true);
			YJKLine hyline = new YJKLine(closeConnector.Origin, closeConnector2.Origin);
			hyline.MakeUnBound();
			XYZ point = (terminal.Location as LocationPoint).Point;
			XYZ xyz = hyline.GetProject(point).Subtract(closeConnector.Origin).Normalize();
			return !xyz.IsAlmostEqualTo(new XYZ(0.0, 0.0, 0.0)) && !xyz.IsAlmostEqualTo(closeConnector.CoordinateSystem.BasisZ.Normalize());
		}

		private bool IsValidDistance(Duct duct, FamilyInstance terminal)
		{
			if (duct == null || terminal == null)
			{
				return false;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			YJKLine hyline = new YJKLine(hypiping.StartConnector.Origin, hypiping.EndConnector.Origin);
			hyline.MakeUnBound();
			XYZ point = (terminal.Location as LocationPoint).Point;
			XYZ project = hyline.GetProject(point);
			double ductWidthorDiameter = YJKRevitTools.GetDuctWidthorDiameter(hypiping.Piping);
			double num = project.DistanceTo(hypiping.StartConnector.Origin);
			double num2 = project.DistanceTo(hypiping.EndConnector.Origin);
			return num > ductWidthorDiameter && num2 > ductWidthorDiameter;
		}

		private IDictionary<double, List<FamilyInstance>> RemoveInvalidItems(IDictionary<double, List<FamilyInstance>> sourceItems, IList<FamilyInstance> toBeRemovedItems)
		{
			IDictionary<double, List<FamilyInstance>> dictionary = new Dictionary<double, List<FamilyInstance>>();
			if (sourceItems == null || toBeRemovedItems == null)
			{
				return null;
			}
			foreach (FamilyInstance item in toBeRemovedItems)
			{
				foreach (KeyValuePair<double, List<FamilyInstance>> keyValuePair in sourceItems)
				{
					keyValuePair.Value.Remove(item);
				}
			}
			foreach (KeyValuePair<double, List<FamilyInstance>> keyValuePair2 in sourceItems)
			{
				if (keyValuePair2.Value.Count > 0)
				{
					dictionary.Add(keyValuePair2.Key, keyValuePair2.Value);
				}
			}
			return dictionary;
		}

		private int ConnectCoveredTerminalsByFitting(Duct duct, IDictionary<double, Dictionary<FamilyInstance, int>> terminalDic, XYZ globalPoint, int terminalConnType, int alignType, out IList<Duct> allSplitDucts)
		{
			int num = 0;
			allSplitDucts = new List<Duct>();
			if (duct == null)
			{
				return num;
			}
			if (terminalDic == null || terminalDic.Count <= 0)
			{
				allSplitDucts.Add(duct);
				return num;
			}
			string empty = string.Empty;
			Duct duct2 = duct;
			bool beFlex = terminalConnType == 1;
			Dictionary<FamilyInstance, int> dictionary = new Dictionary<FamilyInstance, int>();
			foreach (KeyValuePair<double, Dictionary<FamilyInstance, int>> keyValuePair in terminalDic)
			{
				dictionary = keyValuePair.Value;
				int count = dictionary.Count;
				if (count != 1)
				{
					if (count != 2)
					{
						continue;
					}
				}
				else
				{
					using (Dictionary<FamilyInstance, int>.Enumerator enumerator2 = dictionary.GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							KeyValuePair<FamilyInstance, int> keyValuePair2 = enumerator2.Current;
							FamilyInstance key = keyValuePair2.Key;
							int value = keyValuePair2.Value;
							IList<Duct> list = this.ConnectCoveredTerminalByTee(duct2, key, globalPoint, value, ref empty, alignType, beFlex);
							if (list != null && list.Count > 1)
							{
								duct2 = list[1];
								allSplitDucts.Add(list[0]);
								num++;
							}
						}
						continue;
					}
				}
				int[] array = dictionary.Values.ToArray<int>();
				if (array.Length == 2 && array[0] == array[1] && array[0] == 22)
				{
					FamilyInstance[] array2 = dictionary.Keys.ToArray<FamilyInstance>();
					IList<Duct> list = this.ConnTerminalsByCross(duct2, array2[0], array2[1], globalPoint, alignType, beFlex);
					if (list != null && list.Count > 1)
					{
						duct2 = list[1];
						allSplitDucts.Add(list[0]);
						num += 2;
					}
				}
			}
			if (!allSplitDucts.Contains(duct2))
			{
				allSplitDucts.Add(duct2);
			}
			return num;
		}

		private void SetDuctReferenceLevel(Duct newDuct, Duct baseDuct)
		{
			if (!YJKRevitTools.IsRiserDuct(newDuct))
			{
				newDuct.ReferenceLevel = baseDuct.ReferenceLevel;
			}
		}

		private IList<Duct> ConnTerminalsByCross(Duct mainDuct, FamilyInstance terminal1, FamilyInstance terminal2, XYZ globalPoint, int alignType, bool beFlex)
		{
			IList<Duct> list = new List<Duct>();
			SubTransaction subTransaction = null;
			try
			{
				Document document = mainDuct.Document;
				subTransaction = new SubTransaction(document);
				subTransaction.Start();
				this.AlignTerminal(mainDuct, terminal1, alignType);
				this.AlignTerminal(mainDuct, terminal2, alignType);
				Duct duct = this.CreatHDuctAndConnTerminal(mainDuct, terminal1, beFlex);
				Duct duct2 = this.CreatHDuctAndConnTerminal(mainDuct, terminal2, beFlex);
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(mainDuct);
				string connectorSharpName = YJKRevitTools.GetConnectorSharpName(hypiping.StartConnector.Connector);
				YJKPiping<Duct> hySideDuct = new YJKPiping<Duct>(duct);
				XYZ intersectPointDucts = this.GetIntersectPointDucts(hypiping, hySideDuct, false);
				if (intersectPointDucts == null)
				{
					throw new Exception("风口与风管位置不合适.");
				}
				IList<Duct> list2 = hypiping.Separate(intersectPointDucts);
				list2 = this.OrderSplitDucts(list2, globalPoint);
				document.Regenerate();
				List<Duct> list3 = new List<Duct>();
				IList<XYZ> list4 = new List<XYZ>();
				list3.AddRange(list2);
				list3.Add(duct);
				list3.Add(duct2);
				list4.Add((YJKRevitTools.GetElementCurve(list2[0], 0) + YJKRevitTools.GetElementCurve(list2[0], 1)) / 2.0);
				list4.Add((YJKRevitTools.GetElementCurve(list2[1], 0) + YJKRevitTools.GetElementCurve(list2[1], 1)) / 2.0);
				list4.Add((YJKRevitTools.GetElementCurve(duct, 0) + YJKRevitTools.GetElementCurve(duct, 1)) / 2.0);
				list4.Add((YJKRevitTools.GetElementCurve(duct2, 0) + YJKRevitTools.GetElementCurve(duct2, 1)) / 2.0);
				List<string> list5 = new List<string>();
				string empty = string.Empty;
				if (connectorSharpName == "矩形")
				{
					list5 = new ConnectDuctManage().GetRoundAngleCrossNames();
					new ConnectDuctsByFitting().IsConnecteddByCross(list3, list4, list5, ref empty);
				}
				else
				{
					if (!(connectorSharpName == "圆形"))
					{
						throw new Exception("目前不支持椭圆形风管及风口连接！");
					}
					list5.Add("圆形插管四通-顶对齐");
					list5.Add("圆形插管四通-中心对齐");
					list5.Add("圆形插管四通-底对齐");
					new HYDuctConnect().NewCrossFitting(list3, list4, list5, ref empty);
				}
				if (string.IsNullOrEmpty(empty))
				{
					list.Add(list2[0]);
					list.Add(list2[1]);
				}
				document.Regenerate();
				subTransaction.Commit();
			}
			catch (Exception ex)
			{
				string message = ex.Message;
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (subTransaction != null && 3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return list;
		}

		private IDictionary<double, Dictionary<FamilyInstance, int>> GetCoveredTerminals(Duct duct, IDictionary<double, List<FamilyInstance>> terminalsDic, out IList<FamilyInstance> coveredTerminals)
		{
			coveredTerminals = new List<FamilyInstance>();
			if (duct == null || terminalsDic == null)
			{
				return null;
			}
			IDictionary<double, Dictionary<FamilyInstance, int>> dictionary = new Dictionary<double, Dictionary<FamilyInstance, int>>();
			new List<FamilyInstance>();
			HYDuctConnect hyductConnect = new HYDuctConnect();
			string value = string.Empty;
			int num = 0;
			foreach (KeyValuePair<double, List<FamilyInstance>> keyValuePair in terminalsDic)
			{
				Dictionary<FamilyInstance, int> dictionary2 = new Dictionary<FamilyInstance, int>();
				foreach (FamilyInstance familyInstance in ((IEnumerable<FamilyInstance>)keyValuePair.Value))
				{
					value = hyductConnect.CheckTerminalBeCovered(duct, familyInstance, ref num, false);
					if (num == 33 && string.IsNullOrEmpty(value))
					{
						if (dictionary2.Count > 0)
						{
							coveredTerminals.Add(familyInstance);
						}
						else
						{
							dictionary2.Add(familyInstance, num);
							coveredTerminals.Add(familyInstance);
						}
					}
					else if (num == 22 && string.IsNullOrEmpty(value))
					{
						if (dictionary2.Count > 0)
						{
							FamilyInstance key = dictionary2.First<KeyValuePair<FamilyInstance, int>>().Key;
							Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, key);
							Connector elementConnector2 = YJKRevitTools.GetElementConnector((Domain)1, familyInstance);
							if (elementConnector.CoordinateSystem.BasisZ.IsAlmostEqualTo(elementConnector2.CoordinateSystem.BasisZ * -1.0))
							{
								dictionary2.Add(familyInstance, num);
								coveredTerminals.Add(familyInstance);
								break;
							}
							coveredTerminals.Add(familyInstance);
						}
						else
						{
							dictionary2.Add(familyInstance, num);
							coveredTerminals.Add(familyInstance);
						}
					}
				}
				if (dictionary2.Count > 0)
				{
					dictionary.Add(keyValuePair.Key, dictionary2);
				}
			}
			return dictionary;
		}

		private IDictionary<double, List<FamilyInstance>> OrderTerminals(Duct mainDuct, IList<FamilyInstance> terminals, XYZ entrancePnt)
		{
			if (mainDuct == null || terminals == null)
			{
				return null;
			}
			IDictionary<double, List<FamilyInstance>> dictionary = new Dictionary<double, List<FamilyInstance>>();
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(mainDuct);
			Connector closeConnector = hypiping.GetCloseConnector(entrancePnt, false);
			Connector closeConnector2 = hypiping.GetCloseConnector(entrancePnt, true);
			if (closeConnector == null || closeConnector2 == null)
			{
				return null;
			}
			IList<FamilyInstance> list = new List<FamilyInstance>();
			YJKLine hyline = new YJKLine(hypiping.StartConnector.Origin, hypiping.EndConnector.Origin);
			hyline.MakeUnBound();
			FamilyInstance[] array = terminals.ToArray<FamilyInstance>();
			bool flag = true;
            if ((int)closeConnector.Shape == 1)
			{
				flag = true;
			}
			else if (closeConnector.Shape == null)
			{
				flag = false;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if (!list.Contains(array[i]))
				{
					List<FamilyInstance> list2 = new List<FamilyInstance>();
					Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, array[i]);
					double num = 0.0;
					if (flag)
					{
						num = elementConnector.Width;
					}
					else
					{
						Parameter parameter = array[i].GetParameter("风口直径");
						if (parameter != null)
						{
							num = parameter.AsDouble();
						}
					}
					XYZ point = (array[i].Location as LocationPoint).Point;
					XYZ project = hyline.GetProject(point);
					double key = project.DistanceTo(closeConnector.Origin);
					for (int j = i + 1; j < array.Length; j++)
					{
						point = (array[j].Location as LocationPoint).Point;
						XYZ project2 = hyline.GetProject(point);
						double num2 = project2.DistanceTo(project);
						if (project.IsAlmostEqualTo(project2, 0.0001) || num2 < num)
						{
							list2.Add(array[j]);
							list.Add(array[j]);
						}
					}
					list2.Add(array[i]);
					dictionary.Add(key, list2);
				}
			}
			return (from x in dictionary
			orderby x.Key
			select x).ToDictionary((KeyValuePair<double, List<FamilyInstance>> x) => x.Key, (KeyValuePair<double, List<FamilyInstance>> y) => y.Value);
		}

		private int ConnectFarthestTerminals(IList<FamilyInstance> farthestTerminals, Duct duct, int terminalConnType, int alignType, out bool isHandled)
		{
			int result = 0;
			isHandled = true;
			if (farthestTerminals == null || farthestTerminals.Count <= 0)
			{
				return result;
			}
			int num = -1;
			string value = string.Empty;
			List<FamilyInstance> list = new List<FamilyInstance>();
			List<FamilyInstance> list2 = new List<FamilyInstance>();
			List<FamilyInstance> list3 = new List<FamilyInstance>();
			IDictionary<List<FamilyInstance>, int> dictionary = new Dictionary<List<FamilyInstance>, int>();
			HYDuctConnect hyductConnect = new HYDuctConnect();
			foreach (FamilyInstance familyInstance in farthestTerminals)
			{
				value = hyductConnect.CheckTerminalBeCovered(duct, familyInstance, ref num, false);
				if (num == 22 && string.IsNullOrEmpty(value))
				{
					list3.Add(familyInstance);
				}
				else if (num == 33 && string.IsNullOrEmpty(value))
				{
					list2.Add(familyInstance);
				}
				else if (num == 33 && !string.IsNullOrEmpty(value))
				{
					list.Add(familyInstance);
				}
			}
			if (list2.Count > 0)
			{
				dictionary.Add(list2, 33);
			}
			if (list3.Count > 0)
			{
				dictionary.Add(list3, 22);
			}
			if (list.Count > 0)
			{
				dictionary.Add(list, 33);
			}
			if (dictionary.Count <= 0)
			{
				return result;
			}
			List<FamilyInstance> key = dictionary.First<KeyValuePair<List<FamilyInstance>, int>>().Key;
			num = dictionary.First<KeyValuePair<List<FamilyInstance>, int>>().Value;
			int count = key.Count;
			if (count != 1)
			{
				if (count != 2)
				{
					isHandled = false;
				}
				else
				{
					FamilyInstance[] array = key.ToArray();
					YJKPiping<Duct> hyDuct = new YJKPiping<Duct>(duct);
					if (num == 33 && this.IsConnectableDistance(hyDuct, array[0], false, true, 1.5f) && !this.IsConnectableDistance(hyDuct, array[1], false, true, 1.5f))
					{
						result = this.ConnectTerminalByElbow(duct, array[0], terminalConnType, alignType);
					}
					else if (num == 33 && !this.IsConnectableDistance(hyDuct, array[0], false, true, 1.5f) && this.IsConnectableDistance(hyDuct, array[1], false, true, 1.5f))
					{
						result = this.ConnectTerminalByElbow(duct, array[1], terminalConnType, alignType);
					}
					else
					{
						result = this.ConnTerminalByYShapeTee(duct, array[0], array[1], num, terminalConnType, alignType);
					}
				}
			}
			else
			{
				result = this.ConnectTerminalByElbow(duct, key.First<FamilyInstance>(), terminalConnType, alignType);
			}
			return result;
		}

		private bool IsHorTerminal(FamilyInstance terminal)
		{
			if (terminal == null)
			{
				return false;
			}
			XYZ basisZ = YJKRevitTools.GetElementConnector((Domain)1, terminal).CoordinateSystem.BasisZ;
			return basisZ.X == 0.0 && basisZ.Y == 0.0 && basisZ.Z != 0.0;
		}

		private bool IsVerTerminal(FamilyInstance terminal)
		{
			return terminal != null && YJKRevitTools.GetElementConnector((Domain)1, terminal).CoordinateSystem.BasisZ.Z == 0.0;
		}

		private int ConnTerminalByYShapeTee(Duct duct, FamilyInstance terminal1, FamilyInstance terminal2, int connType, int terminalConnType, int alignType)
		{
			int result = 0;
			SubTransaction subTransaction = null;
			try
			{
				Autodesk.Revit.DB.Document document = duct.Document;
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
				ConnectDuctsByFitting connectDuctsByFitting = new ConnectDuctsByFitting();
				subTransaction = new SubTransaction(document);
				subTransaction.Start();
				string connectorSharpName = YJKRevitTools.GetConnectorSharpName(hypiping.StartConnector.Connector);
				bool beFlex = terminalConnType == 1;
				Duct duct2;
				Duct duct3;
				if (connType == 22)
				{
					this.AlignTerminal(duct, terminal1, alignType);
					this.AlignTerminal(duct, terminal2, alignType);
					duct2 = this.CreatHDuctAndConnTerminal(duct, terminal1, beFlex);
					duct3 = this.CreatHDuctAndConnTerminal(duct, terminal2, beFlex);
				}
				else
				{
					if (connType != 33)
					{
						return result;
					}
					duct2 = this.GetTurnDuct(duct, terminal1, beFlex);
					duct3 = this.GetTurnDuct(duct, terminal2, beFlex);
					this.AlignDucts(duct, duct2, alignType);
					this.AlignDucts(duct, duct3, alignType);
				}
				if (duct2 == null || duct3 == null)
				{
					return result;
				}
				List<string> list = new List<string>();
				IList<Duct> list2 = new List<Duct>();
				IList<XYZ> list3 = new List<XYZ>();
				string empty = string.Empty;
				if (connectorSharpName == "矩形")
				{
					list2.Add(duct);
					list3.Add(YJKRevitTools.GetElementCurve(duct, 0) + YJKRevitTools.GetElementCurve(duct, 1) / 2.0);
					list2.Add(duct2);
					list3.Add(YJKRevitTools.GetElementCurve(duct2, 0) + YJKRevitTools.GetElementCurve(duct2, 1) / 2.0);
					list2.Add(duct3);
					list3.Add(YJKRevitTools.GetElementCurve(duct3, 0) + YJKRevitTools.GetElementCurve(duct3, 1) / 2.0);
					list = new ConnectDuctManage().GetYShapeTeeNames();
					if (connectDuctsByFitting.IsConnecteddByYShapeTee(list2, list3, list, ref empty))
					{
						result = 2;
					}
				}
				else
				{
					if (!(connectorSharpName == "圆形"))
					{
						throw new Exception("目前不支持椭圆形风管及风口连接！");
					}
					list2.Add(duct2);
					list3.Add(YJKRevitTools.GetElementCurve(duct2, 0) + YJKRevitTools.GetElementCurve(duct2, 1) / 2.0);
					list2.Add(duct3);
					list3.Add(YJKRevitTools.GetElementCurve(duct3, 0) + YJKRevitTools.GetElementCurve(duct3, 1) / 2.0);
					list2.Add(duct);
					list3.Add(YJKRevitTools.GetElementCurve(duct, 0) + YJKRevitTools.GetElementCurve(duct, 1) / 2.0);
					list.Add("圆形斜角三通-顶对齐");
					list.Add("圆形斜角三通-中心对齐");
					list.Add("圆形斜角三通-底对齐");
					result = ((new HYDuctConnect().NewTeeFittingT(list2, list3, list, ref empty) == null) ? 0 : 2);
				}
				document.Regenerate();
				subTransaction.Commit();
			}
			catch (Exception)
			{
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (subTransaction != null && 3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return result;
		}

		private Duct GetTurnDuct(Duct duct, FamilyInstance terminal, bool beFlex)
		{
			Autodesk.Revit.DB.Document document = duct.Document;
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(this.CreatHDuctAndConnTerminal(duct, terminal, beFlex));
			XYZ origin = elementConnector.Origin;
			XYZ origin2 = hypiping.StartConnector.Origin;
			XYZ origin3 = hypiping.EndConnector.Origin;
			YJKLine hyline = new YJKLine(origin2, origin3);
			hyline.MakeUnBound();
			XYZ project = hyline.GetProject(origin);
			XYZ xyz = new XYZ(origin.X, origin.Y, project.Z);
			Duct duct2 = YJKRevitTools.NewDuct(hypiping.Piping, project, xyz);
			document.Regenerate();
			hyrotateFamilyInstance.MovePiping(duct2);
			this.DuctSetParameter(elementConnector, duct2, false);
			YJKPiping<Duct> hypiping3 = new YJKPiping<Duct>(duct2);
			if (hypiping2.BeRotateDuct(duct2))
			{
				hypiping3.Rotate90();
			}
			this.ConnElbowDucts(hypiping2, hypiping3, xyz, document);
			document.Regenerate();
			hyrotateFamilyInstance.MovePiping(duct2);
			return duct2;
		}

		private void GetConnectors(Duct duct, XYZ globalPoint, ref Connector sConnector, ref Connector eConnector)
		{
			if (duct == null)
			{
				return;
			}
			List<Connector> connectorEnd = YJKRevitTools.GetConnectorEnd(duct);
			if (connectorEnd.Count != 2)
			{
				throw new Exception("获取连接器个数失败！");
			}
			if (globalPoint.DistanceTo(connectorEnd[0].Origin) <= globalPoint.DistanceTo(connectorEnd[1].Origin))
			{
				sConnector = connectorEnd[0];
				eConnector = connectorEnd[1];
			}
			else
			{
				sConnector = connectorEnd[1];
				eConnector = connectorEnd[0];
			}
			if (sConnector == null || eConnector == null)
			{
				throw new Exception("获取风管连接器失败！");
			}
		}

		private IList<FamilyInstance> FilterTerminals(Duct duct, IList<FamilyInstance> terminals, Connector sConnector, Connector eConnector)
		{
			IList<FamilyInstance> list = new List<FamilyInstance>();
			if (sConnector == null || eConnector == null || terminals == null || terminals.Count <= 0)
			{
				return list;
			}
			ConnectHelper connectHelper = new ConnectHelper();
			HYDuctConnect hyductConnect = new HYDuctConnect();
			YJKPiping<Duct> hyDuct = new YJKPiping<Duct>(duct);
			int num = -1;
			string empty = string.Empty;
			YJKLine hyline = new YJKLine(sConnector.Origin, eConnector.Origin);
			hyline.MakeUnBound();
			foreach (FamilyInstance familyInstance in terminals)
			{
				Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, familyInstance);
				if (!elementConnector.IsConnected && connectHelper.IsSupportConnect(sConnector, elementConnector))
				{
					XYZ point = (familyInstance.Location as LocationPoint).Point;
					XYZ project = hyline.GetProject(point);
					XYZ xyz = project.Subtract(sConnector.Origin).Normalize();
					XYZ xyz2 = project.Subtract(eConnector.Origin).Normalize();
					XYZ xyz3 = sConnector.CoordinateSystem.BasisZ.Normalize();
					XYZ xyz4 = eConnector.CoordinateSystem.BasisZ.Normalize();
					if (this.IsPerpendicular(elementConnector.CoordinateSystem.BasisZ.Normalize(), xyz3))
					{
						if (string.IsNullOrEmpty(hyductConnect.CheckTerminalBeCovered(duct, familyInstance, ref num, false)))
						{
							if (!this.IsConnectableDistance(hyDuct, familyInstance, true, false, 1.5f))
							{
								continue;
							}
						}
						else if (!this.IsConnectableDistance(hyDuct, familyInstance, false, false, 1.5f))
						{
							continue;
						}
						if (sConnector.IsConnected && eConnector.IsConnected)
						{
							if (xyz.IsAlmostEqualTo(xyz3 * -1.0) && xyz2.IsAlmostEqualTo(xyz4 * -1.0))
							{
								list.Add(familyInstance);
							}
						}
						else if (!sConnector.IsConnected && !eConnector.IsConnected)
						{
							if (xyz.IsAlmostEqualTo(xyz3 * -1.0) || xyz.IsAlmostEqualTo(new XYZ(0.0, 0.0, 0.0)))
							{
								list.Add(familyInstance);
							}
						}
						else if (sConnector.IsConnected && !eConnector.IsConnected)
						{
							if (xyz.IsAlmostEqualTo(xyz3 * -1.0))
							{
								list.Add(familyInstance);
							}
						}
						else if ((xyz.IsAlmostEqualTo(xyz3 * -1.0) || xyz.IsAlmostEqualTo(new XYZ(0.0, 0.0, 0.0))) && xyz2.IsAlmostEqualTo(xyz4 * -1.0))
						{
							list.Add(familyInstance);
						}
					}
				}
			}
			return list;
		}

		public bool CheckProjectionInExtDuct(IList<FamilyInstance> terminals, Connector startConnector, Connector endConnector, out IList<FamilyInstance> farestTerminals)
		{
			bool result = false;
			farestTerminals = new List<FamilyInstance>();
			if (terminals == null || endConnector == null || terminals.Count <= 0)
			{
				return result;
			}
			double num = 0.0;
			YJKLine hyline = new YJKLine(startConnector.Origin, endConnector.Origin);
			hyline.MakeUnBound();
			foreach (FamilyInstance familyInstance in terminals)
			{
				XYZ point = (familyInstance.Location as LocationPoint).Point;
				XYZ project = hyline.GetProject(point);
				if (project.Subtract(endConnector.Origin).Normalize().IsAlmostEqualTo(endConnector.CoordinateSystem.BasisZ.Normalize()))
				{
					double num2 = project.DistanceTo(endConnector.Origin);
					if (num2 - num > 0.001)
					{
						farestTerminals.Clear();
						farestTerminals.Add(familyInstance);
						num = num2;
					}
					else if (Math.Abs(num2 - num) <= 0.001)
					{
						farestTerminals.Add(familyInstance);
					}
				}
			}
			return farestTerminals.Count > 0;
		}

		private IList<FamilyInstance> GetFarthestTerminals(IList<FamilyInstance> terminals, Connector startConnector, Connector endConnector)
		{
			IList<FamilyInstance> result = new List<FamilyInstance>();
			if (terminals == null || endConnector == null || terminals.Count <= 0)
			{
				return result;
			}
			double num = 0.0;
			Dictionary<double, IList<FamilyInstance>> dictionary = new Dictionary<double, IList<FamilyInstance>>();
			IList<FamilyInstance> list = new List<FamilyInstance>();
			YJKLine hyline = new YJKLine(startConnector.Origin, endConnector.Origin);
			hyline.MakeUnBound();
			foreach (FamilyInstance familyInstance in terminals)
			{
				XYZ point = (familyInstance.Location as LocationPoint).Point;
				XYZ project = hyline.GetProject(point);
				if (project.Subtract(endConnector.Origin).Normalize().IsAlmostEqualTo(endConnector.CoordinateSystem.BasisZ.Normalize()))
				{
					double num2 = project.DistanceTo(endConnector.Origin);
					if (num2 - num > 0.1)
					{
						dictionary.Clear();
						list.Clear();
						num = num2;
						list.Add(familyInstance);
						dictionary.Add(num, list);
					}
					else if (Math.Abs(num2 - num) < 0.001)
					{
						list.Add(familyInstance);
					}
				}
			}
			if (!dictionary.IsEmpty<KeyValuePair<double, IList<FamilyInstance>>>())
			{
				result = list;
			}
			return result;
		}

		public IList<Duct> ConnectCoveredTerminalByTee(Duct duct, FamilyInstance terminal, XYZ globalPoint, int connType, ref string connMsg, int alignType = 1, bool beFlex = false)
		{
			connMsg = string.Empty;
			if (duct == null || terminal == null)
			{
				return null;
			}
			IList<Duct> result = new List<Duct>();
			SubTransaction subTransaction = null;
			try
			{
				subTransaction = new SubTransaction(duct.Document);
				subTransaction.Start();
				if (connType == 33)
				{
					this.MoveTerminalCenterToAlign(duct, terminal);
					Duct duct2 = this.CreatHDuctAndConnTerminal(duct, terminal, beFlex);
					if (duct2 == null)
					{
						return null;
					}
					result = this.ConnectTerminalByTee(duct, duct2, globalPoint, true, ref connMsg);
				}
				else
				{
					this.AlignTerminal(duct, terminal, alignType);
					Duct duct3 = this.CreatHDuctAndConnTerminal(duct, terminal, beFlex);
					if (duct3 == null)
					{
						return null;
					}
					result = this.ConnectTerminalByTee(duct, duct3, globalPoint, false, ref connMsg);
				}
				subTransaction.Commit();
			}
			catch (Exception ex)
			{
				connMsg = ex.Message;
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (subTransaction != null && 3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return result;
		}

		public IList<Duct> ConnectHorTerminal(Duct duct, FamilyInstance terminal, XYZ globalPoint, ref string connMSG, bool beflex = false)
		{
			connMSG = string.Empty;
			IList<Duct> result = new List<Duct>();
			SubTransaction subTransaction = null;
			if (duct == null || terminal == null)
			{
				return result;
			}
			try
			{
				subTransaction = new SubTransaction(duct.Document);
				subTransaction.Start();
				this.MoveTerminalCenterToAlign(duct, terminal);
				Duct duct2 = this.CreatHDuctAndConnTerminal(duct, terminal, beflex);
				if (duct2 == null)
				{
					return result;
				}
				result = this.ConnectTerminalByTee(duct, duct2, globalPoint, true, ref connMSG);
				subTransaction.Commit();
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (subTransaction != null && 3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return result;
		}

		public IList<Duct> ConnectSideTerminal(Duct duct, FamilyInstance terminal, XYZ globalPoint, int alignType, ref string connMSG, bool beflex = false)
		{
			IList<Duct> result = null;
			connMSG = string.Empty;
			SubTransaction subTransaction = null;
			if (duct == null || terminal == null)
			{
				return result;
			}
			try
			{
				Autodesk.Revit.DB.Document document = duct.Document;
				new YJKPiping<Duct>(duct);
				Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
				subTransaction = new SubTransaction(document);
				subTransaction.Start();
				if (elementConnector != null && elementConnector.IsConnected)
				{
					connMSG = "风口已经有风管连接";
					return result;
				}
				Duct duct2 = this.CreatHDuctAndConnTerminal(duct, terminal, beflex);
				this.AlignDucts(duct, duct2, alignType);
				result = this.ConnectTerminalByTee(duct, duct2, globalPoint, false, ref connMSG);
				subTransaction.Commit();
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (subTransaction != null && 3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return result;
		}

		private IList<Duct> ConnectTerminalByTee(Duct duct, Duct newDuct, XYZ globalPoint, bool centerAlign, ref string connMSG)
		{
			if (duct == null || newDuct == null)
			{
				return null;
			}
			IList<Duct> result = new List<Duct>();
			try
			{
				Autodesk.Revit.DB.Document document = duct.Document;
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
				YJKPiping<Duct> hySideDuct = new YJKPiping<Duct>(newDuct);
				YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
				ConnectDuctsByFitting connectDuctsByFitting = new ConnectDuctsByFitting();
				string connectorSharpName = YJKRevitTools.GetConnectorSharpName(hypiping.StartConnector.Connector);
				XYZ intersectPointDucts = this.GetIntersectPointDucts(hypiping, hySideDuct, centerAlign);
				if (intersectPointDucts == null)
				{
					throw new Exception("风口与风管位置不合适.");
				}
				IList<Duct> list = hypiping.Separate(intersectPointDucts);
				document.Regenerate();
				if (list != null)
				{
					hyrotateFamilyInstance.MovePiping(list[0]);
					hyrotateFamilyInstance.MovePiping(list[1]);
					IList<Duct> list2 = new List<Duct>();
					IList<XYZ> list3 = new List<XYZ>();
					list2 = this.OrderSplitDucts(list, globalPoint);
					list2.Add(newDuct);
					List<string> list4 = new List<string>();
					list3.Add((YJKRevitTools.GetElementCurve(list2[0], 0) + YJKRevitTools.GetElementCurve(list2[0], 1)) / 2.0);
					list3.Add((YJKRevitTools.GetElementCurve(list2[1], 0) + YJKRevitTools.GetElementCurve(list2[1], 1)) / 2.0);
					list3.Add((YJKRevitTools.GetElementCurve(list2[2], 0) + YJKRevitTools.GetElementCurve(list2[2], 1)) / 2.0);
					HYDuctConnect hyductConnect = new HYDuctConnect();
					if (connectorSharpName == "矩形")
					{
						ConnectDuctManage connectDuctManage = new ConnectDuctManage();
						if (YJKRevitTools.IsRiserDuct(newDuct))
						{
							string familySymbolName = "矩形圆角变径三通_水平中_竖直中对齐_法兰";
							hyductConnect.NewTeeFittingHT(list2, list3, familySymbolName, ref connMSG, true);
						}
						else
						{
							list4 = connectDuctManage.GetRoundAngleTeeNames();
							connectDuctsByFitting.IsConnecteddByRoundAngleTee(list2, list3, list4, ref connMSG);
						}
					}
					else
					{
						if (!(connectorSharpName == "圆形"))
						{
							throw new Exception("目前不支持椭圆形风管及风口连接！");
						}
						list4.Add("圆形直角三通-顶对齐");
						list4.Add("圆形直角三通-中心对齐");
						list4.Add("圆形直角三通-底对齐");
						if (YJKRevitTools.IsRiserDuct(newDuct))
						{
							hyductConnect.NewTeeFittingHT(list2, list3, list4, ref connMSG);
						}
						else
						{
							hyductConnect.NewTeeFittingT(list2, list3, list4, ref connMSG);
						}
					}
					result = list2;
				}
				document.Regenerate();
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		private XYZ GetIntersectPointDucts(YJKPiping<Duct> hyMainDuct, YJKPiping<Duct> hySideDuct, bool centerAlign = false)
		{
			XYZ result;
			if (centerAlign)
			{
				YJKLine ductHYLine = this.GetDuctHYLine(hyMainDuct, false);
				YJKLine ductHYLine2 = this.GetDuctHYLine(hySideDuct, false);
				result = ductHYLine.IntersectionPoint(ductHYLine2.Line);
			}
			else
			{
				YJKLine ductHYLine3 = this.GetDuctHYLine(hyMainDuct, true);
				YJKLine ductHYLine4 = this.GetDuctHYLine(hySideDuct, true);
				XYZ point = ductHYLine3.IntersectionPoint(ductHYLine4.Line);
				result = this.GetDuctHYLine(hyMainDuct, false).GetProject(point);
			}
			return result;
		}

		private YJKLine GetDuctHYLine(YJKPiping<Duct> hyMainDuct, bool bePlance = true)
		{
			XYZ start;
			XYZ end;
			if (bePlance)
			{
				start = YJKRevitTools.SetZToZero(hyMainDuct.StartConnector.Origin);
				end = YJKRevitTools.SetZToZero(hyMainDuct.EndConnector.Origin);
			}
			else
			{
				start = hyMainDuct.StartConnector.Origin;
				end = hyMainDuct.EndConnector.Origin;
			}
			YJKLine hyline = new YJKLine(start, end);
			hyline.MakeUnBound();
			return hyline;
		}

		private Duct CreatHDuctAndConnTerminal(Duct duct, FamilyInstance terminal, bool beFlex)
		{
			Duct duct2 = null;
			if (terminal == null || duct == null)
			{
				return duct2;
			}
			Autodesk.Revit.DB.Document document = duct.Document;
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			YJKPiping<Duct> myDuct = new YJKPiping<Duct>(duct);
			Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
			if (beFlex)
			{
				duct2 = this.FlexDuctConnection(document, elementConnector, myDuct);
				hyrotateFamilyInstance.MovePiping(duct2);
			}
			else
			{
				XYZ startXYZ = elementConnector.Origin + elementConnector.CoordinateSystem.BasisZ * (double)this.LeadDuctLength / 304.8;
				duct2 = YJKRevitTools.NewDuct(duct, startXYZ, elementConnector.Origin);
				document.Regenerate();
				this.DuctSetParameter(elementConnector, duct2, false);
				hyrotateFamilyInstance.MovePiping(duct2);
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct2);
				if (hypiping.BeRotateDuct(terminal))
				{
					hypiping.Rotate90();
				}
				hypiping.GetCloseConnector(elementConnector.Origin, false).ConnectTo(elementConnector);
				document.Regenerate();
			}
			if (duct2 != null && duct != null)
			{
				this.SetDuctReferenceLevel(duct2, duct);
			}
			return duct2;
		}

		public bool DirectConnectTerminal(Duct duct, FamilyInstance terminal, ref string connMSG, bool beFlex = false)
		{
			bool result = false;
			SubTransaction subTransaction = null;
			try
			{
				Autodesk.Revit.DB.Document document = duct.Document;
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
				subTransaction = new SubTransaction(document);
				subTransaction.Start();
				this.MoveTerminalCenterToAlign(duct, terminal);
				YJKPiping<Duct> hyNewDuct = new YJKPiping<Duct>(this.CreatHDuctAndConnTerminal(duct, terminal, beFlex));
				FamilySymbol firstFS = this.ChangePreferences(hypiping, document, "插接头");
				result = this.ConnectTerminalTakeOff(hypiping, hyNewDuct, firstFS);
				document.Regenerate();
				subTransaction.Commit();
			}
			catch (Exception ex)
			{
				connMSG = ex.Message;
				throw ex;
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (subTransaction != null && 3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return result;
		}

		private bool ConnectTerminalTakeOff(YJKPiping<Duct> hyMainDuct, YJKPiping<Duct> hyNewDuct, FamilySymbol firstFS)
		{
			bool result = false;
			try
			{
				this.MoveNewDuct(hyMainDuct, hyNewDuct.Piping);
				if (this.ConnectDucts(new List<Duct>
				{
					hyMainDuct.Piping,
					hyNewDuct.Piping
				}, new List<XYZ>
				{
					hyMainDuct.StartConnector.Origin,
					hyNewDuct.StartConnector.Origin
				}, firstFS) != null)
				{
					result = true;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		public bool DirectSideConnectTerminal(Duct duct, FamilyInstance terminal, int connType, int alignType, ref string connMSG, bool beFlex = false)
		{
			bool flag = false;
			SubTransaction subTransaction = null;
			try
			{
				Autodesk.Revit.DB.Document document = duct.Document;
				YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
				Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
				subTransaction = new SubTransaction(document);
				subTransaction.Start();
				Duct duct3;
				if (connType == 33)
				{
					YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(this.CreatHDuctAndConnTerminal(duct, terminal, beFlex));
					XYZ origin = elementConnector.Origin;
					XYZ origin2 = hypiping.StartConnector.Origin;
					XYZ origin3 = hypiping.EndConnector.Origin;
					YJKLine hyline = new YJKLine(origin2, origin3);
					hyline.MakeUnBound();
					XYZ project = hyline.GetProject(origin);
					XYZ xyz = new XYZ(origin.X, origin.Y, project.Z);
					Duct duct2 = YJKRevitTools.NewDuct(hypiping.Piping, project, xyz);
					document.Regenerate();
					hyrotateFamilyInstance.MovePiping(duct2);
					this.DuctSetParameter(elementConnector, duct2, false);
					YJKPiping<Duct> hypiping3 = new YJKPiping<Duct>(duct2);
					if (hypiping2.BeRotateDuct(duct2))
					{
						hypiping3.Rotate90();
					}
					this.AlignDucts(duct, duct2, alignType);
					this.ConnElbowDucts(hypiping2, hypiping3, xyz, document);
					document.Regenerate();
					duct3 = duct2;
				}
				else
				{
					this.AlignTerminal(duct, terminal, alignType);
					duct3 = this.CreatHDuctAndConnTerminal(duct, terminal, beFlex);
				}
				if (duct3 != null)
				{
					FamilySymbol firstFS = this.ChangePreferences(hypiping, document, "插接头");
					YJKPiping<Duct> hyNewDuct = new YJKPiping<Duct>(duct3);
					flag = this.ConnectTerminalTakeOff(hypiping, hyNewDuct, firstFS);
					if (flag)
					{
						this.AlignDucts(hypiping.Piping, duct3, alignType);
					}
				}
				document.Regenerate();
				subTransaction.Commit();
			}
			catch (Exception ex)
			{
				connMSG = ex.Message;
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (subTransaction != null && 3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return flag;
		}

		private void ConnElbowDucts(YJKPiping<Duct> hyDuct1, YJKPiping<Duct> hyDuct2, XYZ point, Autodesk.Revit.DB.Document doc)
		{
			Connector nearConnectorToPoint = hyDuct1.GetNearConnectorToPoint(point);
			Connector nearConnectorToPoint2 = hyDuct2.GetNearConnectorToPoint(point);
			doc.Create.NewElbowFitting(nearConnectorToPoint, nearConnectorToPoint2);
		}

		private void AlignDucts(Duct baseDuct, Duct changeDuct, int alignType)
		{
			if (baseDuct == null || changeDuct == null)
			{
				return;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(baseDuct);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(changeDuct);
			double heightOrDiameter = hypiping.GetHeightOrDiameter();
			double z = hypiping.StartConnector.Origin.Z;
			double heightOrDiameter2 = hypiping2.GetHeightOrDiameter();
			double z2 = hypiping2.StartConnector.Origin.Z;
			XYZ xyz = new XYZ(0.0, 0.0, 1.0);
			double num = 0.0;
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			if (alignType == 0)
			{
				num = z + heightOrDiameter / 2.0 - heightOrDiameter2 / 2.0 - z2;
			}
			else if (alignType == 2)
			{
				num = z - heightOrDiameter / 2.0 + heightOrDiameter2 / 2.0 - z2;
			}
			else if (alignType == 1)
			{
				num = z - z2;
			}
			hyrotateFamilyInstance.MoveElement(num * xyz, changeDuct);
			baseDuct.Document.Regenerate();
		}

		private void AlignTerminal(Duct baseDuct, FamilyInstance terminal, int alignType)
		{
			if (baseDuct == null || terminal == null)
			{
				return;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(baseDuct);
			double heightOrDiameter = hypiping.GetHeightOrDiameter();
			double z = hypiping.StartConnector.Origin.Z;
			Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
			double height = elementConnector.Height;
			double z2 = elementConnector.Origin.Z;
			XYZ xyz = new XYZ(0.0, 0.0, 1.0);
			double num = 0.0;
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			if (alignType == 0)
			{
				num = z + heightOrDiameter / 2.0 - height / 2.0 - z2;
			}
			else if (alignType == 2)
			{
				num = z - heightOrDiameter / 2.0 + height / 2.0 - z2;
			}
			else if (alignType == 1)
			{
				num = z - z2;
			}
			hyrotateFamilyInstance.MoveElement(num * xyz, terminal);
			baseDuct.Document.Regenerate();
		}

		private bool IsConnectSameDirection(Connector connector1, Connector connector2)
		{
			double num = connector1.CoordinateSystem.BasisY.AngleTo(connector2.CoordinateSystem.BasisY);
			return Math.Abs(num - 0.0) < 0.001 || Math.Abs(num - Math.PI) < 0.001;
		}

		private bool CheckSubpointOnCurve(Connector fiConn, YJKPiping<Duct> hyDuct)
		{
			bool result = false;
			XYZ origin = fiConn.Origin;
			XYZ origin2 = hyDuct.StartConnector.Origin;
			XYZ origin3 = hyDuct.EndConnector.Origin;
			YJKLine hyline = new YJKLine(origin2, origin3);
			hyline.MakeUnBound();
			XYZ project = hyline.GetProject(origin);
			if (hyline.IsPointOnCurveLine(project))
			{
				result = true;
			}
			return result;
		}

		private void MoveTerminalCenterToAlign(Duct duct, FamilyInstance terminal)
		{
			if (duct == null || terminal == null)
			{
				return;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
			if (elementConnector == null)
			{
				return;
			}
			XYZ point = (terminal.Location as LocationPoint).Point;
			XYZ origin = hypiping.StartConnector.Origin;
			XYZ origin2 = hypiping.EndConnector.Origin;
			XYZ xyz = null;
			if (elementConnector.CoordinateSystem.BasisZ.IsAlmostEqualTo(new XYZ(0.0, 0.0, 1.0), 0.0001) || elementConnector.CoordinateSystem.BasisZ.IsAlmostEqualTo(new XYZ(0.0, 0.0, 1.0) * -1.0, 0.0001))
			{
				YJKLine hyline = new YJKLine(origin, origin2);
				hyline.MakeUnBound();
				XYZ project = hyline.GetProject(point);
				xyz = new XYZ(project.X, project.Y, point.Z);
			}
			else if (elementConnector.CoordinateSystem.BasisZ.Normalize().Z < 0.0001 && elementConnector.CoordinateSystem.BasisZ.Normalize().Z > -0.0001)
			{
				xyz = new XYZ(point.X, point.Y, origin.Z);
			}
			if (xyz != null)
			{
				new YJKRotateFamilyInstance().MoveElem(terminal, xyz);
				duct.Document.Regenerate();
			}
		}

		private void DuctSetParameter(Connector connector, Duct duct, bool isNozzle = false)
		{
			if (connector.Shape == ConnectorSharp.Rect)
			{
				double height = connector.Height;
				double width = connector.Width;
				ElementId elementId;
				if (connector.Owner.GetYJKLevel() != null)
				{
					elementId = connector.Owner.GetYJKLevel().Id;
				}
				else
				{
					elementId = connector.Owner.GetParameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM).AsElementId();
				}
				if (duct.GetParameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM) != null)
				{
					Parameter parameter = duct.GetParameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM);
					Parameter parameter2 = duct.GetParameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM);
					if (isNozzle)
					{
						parameter.Set(height);
						parameter2.Set(width);
					}
					else
					{
						parameter.Set(height);
						parameter2.Set(width);
					}
				}
				else
				{
					duct.GetParameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).Set(height);
				}
				duct.GetParameter(BuiltInParameter.RBS_START_LEVEL_PARAM).Set(elementId);
				return;
			}
			if (connector.Shape == ConnectorSharp.Round)
			{
				double radius = connector.Radius;
				ElementId elementId2;
				if (connector.Owner.GetYJKLevel() != null)
				{
					elementId2 = connector.Owner.GetYJKLevel().Id;
				}
				else
				{
					elementId2 = connector.Owner.GetParameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM).AsElementId();
				}
				if (duct.GetParameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM) != null)
				{
					duct.GetParameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).Set(radius * 2.0);
				}
				else
				{
					duct.GetParameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).Set(radius * 2.0);
					duct.GetParameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).Set(radius * 2.0);
				}
				duct.GetParameter(BuiltInParameter.RBS_START_LEVEL_PARAM).Set(elementId2);
			}
		}

		private XYZ GetConnectorDirectionPoint(Connector connector)
		{
			XYZ result = null;
			if (connector != null)
			{
				Transform coordinateSystem = connector.CoordinateSystem;
				result = connector.Origin + 0.1 * coordinateSystem.BasisZ;
			}
			return result;
		}

		private XYZ GetCurveIntersection(Curve curve1, Curve curve2)
		{
			XYZ result = new XYZ();
			result = null;
			IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
			SetComparisonResult setComparisonResult = curve1.Intersect(curve2, out intersectionResultArray);
			if (4 != (int)setComparisonResult && !intersectionResultArray.IsEmpty)
			{
				result = intersectionResultArray.get_Item(0).XYZPoint;
			}
			return result;
		}

		private FamilySymbol ChangePreferences(YJKPiping<Duct> hyDuct, Autodesk.Revit.DB.Document doc, string familySymbolName)
		{
			bool flag = false;
			List<Element> elementByCategory = YJKElementFilter.GetElementByCategory(doc, typeof(FamilySymbol), BuiltInCategory.OST_DuctFitting);
			FamilySymbol result = null;
			foreach (Element element in elementByCategory)
			{
				if ((element as FamilySymbol).Family.Name == familySymbolName)
				{
					flag = true;
					result = (element as FamilySymbol);
					break;
				}
			}
			if (!flag)
			{
				Family family = null;
				string text = Path.Combine(Product.FamilyLocation, RevitVersion.Version, "Fitting", string.Format("{0}.rfa", familySymbolName));
				if (doc.LoadFamily(text, out family))
				{
					foreach (FamilySymbol familySymbol in family.GetSymbols())
					{
						if (familySymbol != null)
						{
							result = familySymbol;
							break;
						}
					}
				}
			}
			return result;
		}

		private FamilySymbol ChangeFirstTakeOff(YJKPiping<Duct> hyDuct, Autodesk.Revit.DB.Document doc, int nozzleType)
		{
			bool flag = false;
			List<Element> elementByCategory = YJKElementFilter.GetElementByCategory(doc, typeof(FamilySymbol), BuiltInCategory.OST_DuctFitting);
			FamilySymbol familySymbol = null;
			string text = (nozzleType == 0) ? "插接头" : "圆形活接头";
			foreach (Element element in elementByCategory)
			{
				FamilySymbol familySymbol2 = element as FamilySymbol;
				if (familySymbol2 != null && familySymbol2.Family.Name == text)
				{
					flag = true;
					familySymbol = (element as FamilySymbol);
					break;
				}
			}
			if (!flag)
			{
				Family family = null;
				string path = text + ".rfa";
				string text2 = Path.Combine(Product.FamilyLocation, RevitVersion.Version, "Fitting", path);
				if (doc.LoadFamily(text2, out family))
				{
					foreach (FamilySymbol familySymbol3 in family.GetSymbols())
					{
						if (familySymbol3 != null)
						{
							familySymbol = familySymbol3;
							break;
						}
					}
				}
			}
			if (!hyDuct.CheckFirstTakeOff(text))
			{
				hyDuct.ChangeFirstTakeOff(familySymbol);
			}
			return familySymbol;
		}

		public FamilyInstance ConnectDucts(IList<Duct> ducts, IList<XYZ> xyzs, FamilySymbol fs)
		{
			FamilyInstance familyInstance = null;
			FamilyInstance result;
			try
			{
				if (ducts.Count < 2 || xyzs.Count < 2)
				{
					throw new System.ArgumentNullException("Duct or XYZ", "is null");
				}
				Autodesk.Revit.DB.Document document = ducts[0].Document;
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(ducts[0], xyzs[0]);
				YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(ducts[1], xyzs[1]);
				IList<RoutingPreferenceRule> segmentRuleFitting = UnifiedModified.GetSegmentRuleFitting(ducts[0].DuctType, 6);
				if (!hypiping.CheckFirstTakeOff(fs.FamilyName))
				{
					hypiping.ChangeFirstTakeOff(fs);
				}
				if (!hypiping2.CheckFirstTakeOff(fs.FamilyName))
				{
					hypiping2.ChangeFirstTakeOff(fs);
				}
				document.Regenerate();
				XYZ xyz = hypiping.IntersectionPoint(hypiping2.Piping);
				if (xyz != null)
				{
					Duct duct = null;
					Connector connector = null;
					if (hypiping.IsPointOnPipingCurve(xyz))
					{
						duct = hypiping.Piping;
						connector = hypiping2.GetAppropriateConnector(xyz);
					}
					else if (hypiping2.IsPointOnPipingCurve(xyz))
					{
						duct = hypiping2.Piping;
						connector = hypiping.GetAppropriateConnector(xyz);
					}
					if (duct == null || connector == null || connector.IsConnected)
					{
						throw new Exception("风管已经连接");
					}
					familyInstance = document.Create.NewTakeoffFitting(connector, duct);
				}
				UnifiedModified.SetSegmentRuleFitting(ducts[0].DuctType, 6, segmentRuleFitting);
				result = familyInstance;
			}
			catch (Exception ex)
			{
				if (!ex.Message.Contains("风管已经连接"))
				{
					throw new Exception("连接失败，风管位置与风口位置不合适！");
				}
				throw ex;
			}
			return result;
		}

		private void MoveNewDuct(YJKPiping<Duct> hyDuct, Duct newDuct)
		{
			YJKLine hyline = new YJKLine(hyDuct.StartConnector.Origin, hyDuct.EndConnector.Origin);
			hyline.MakeUnBound();
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(newDuct);
			XYZ origin = hypiping.StartConnector.Origin;
			XYZ xyz = hypiping.StartConnector.Origin.Subtract(hypiping.EndConnector.Origin).Normalize();
			XYZ project = hyline.GetProject(origin);
			YJKLine hyline2 = new YJKLine(project, project.Add(xyz));
			hyline2.MakeUnBound();
			XYZ xyz2 = hyline2.GetProject(origin).Subtract(origin);
			if (xyz2 == null || xyz2.IsAlmostEqualTo(new XYZ(0.0, 0.0, 0.0), 0.0001))
			{
				return;
			}
			new YJKRotateFamilyInstance().MoveElement(xyz2, newDuct);
		}

		public IList<Duct> OrderSplitDucts(IList<Duct> mainDucts, XYZ globalPoint)
		{
			IList<Duct> list = new List<Duct>();
			if (mainDucts == null || mainDucts.Count < 2)
			{
				return list;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(mainDucts[0]);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(mainDucts[1]);
			YJKLine hyline = new YJKLine(hypiping.StartConnector.Origin, hypiping.EndConnector.Origin);
			hyline.MakeUnBound();
			YJKLine hyline2 = new YJKLine(hypiping2.StartConnector.Origin, hypiping2.EndConnector.Origin);
			hyline2.MakeUnBound();
			XYZ project = hyline.GetProject(globalPoint);
			XYZ project2 = hyline2.GetProject(globalPoint);
			if (hyline.IsPointOnLine(project))
			{
				list.Add(mainDucts[0]);
				list.Add(mainDucts[1]);
			}
			else if (hyline2.IsPointOnLine(project2))
			{
				list.Add(mainDucts[1]);
				list.Add(mainDucts[0]);
			}
			else
			{
				XYZ xyz = (YJKRevitTools.GetElementCurve(mainDucts[0], 0) + YJKRevitTools.GetElementCurve(mainDucts[0], 1)) / 2.0;
				XYZ xyz2 = (YJKRevitTools.GetElementCurve(mainDucts[1], 0) + YJKRevitTools.GetElementCurve(mainDucts[1], 1)) / 2.0;
				if (xyz.DistanceTo(globalPoint) <= xyz2.DistanceTo(globalPoint))
				{
					list.Add(mainDucts[0]);
					list.Add(mainDucts[1]);
				}
				else
				{
					list.Add(mainDucts[1]);
					list.Add(mainDucts[0]);
				}
			}
			return list;
		}

		private static void RotateTerminal(FamilyInstance sideTerminal, YJKPiping<Duct> hyDuct, Duct newDuct, Autodesk.Revit.DB.Document doc)
		{
			if (sideTerminal.HandOrientation.Normalize().IsAlmostEqualTo(XYZ.BasisZ) || sideTerminal.HandOrientation.Normalize().IsAlmostEqualTo(-XYZ.BasisZ))
			{
				LocationCurve locationCurve = hyDuct.Piping.Location as LocationCurve;
				if (locationCurve != null && locationCurve.Curve as Line != null)
				{
					XYZ direction = (locationCurve.Curve as Line).Direction;
					YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
					double num = doc.ActiveView.RightDirection.Normalize().AngleTo(direction);
					num = ((direction.AngleTo(doc.ActiveView.UpDirection) > Math.PI*.5) ? (Math.PI - num) : num);
					hyrotateFamilyInstance.RotateElem(doc, sideTerminal, num * 180.0 / Math.PI);
					List<ElementId> list = new List<ElementId>
					{
						newDuct.Id
					};
					Line line = Line.CreateBound((sideTerminal.Location as LocationPoint).Point, (sideTerminal.Location as LocationPoint).Point + XYZ.BasisZ);
					if (line != null)
					{
						ElementTransformUtils.RotateElements(doc, list, line, Math.PI*.5 + num);
					}
					doc.Regenerate();
				}
			}
		}

		private int ConnectTerminalByElbow(Duct duct, FamilyInstance terminal, int terminalConnType, int alignType)
		{
			int result = 0;
			SubTransaction subTransaction = null;
			if (duct == null || terminal == null)
			{
				return result;
			}
			try
			{
				Autodesk.Revit.DB.Document document = duct.Document;
				YJKRevitTools.GetElementConnector((Domain)1, terminal);
				subTransaction = new SubTransaction(document);
				subTransaction.Start();
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
				YJKLine hyline = new YJKLine(hypiping.StartConnector.Origin, hypiping.EndConnector.Origin);
				XYZ point = (terminal.Location as LocationPoint).Point;
				XYZ project = hyline.GetProject(point);
				if (project == null)
				{
					return result;
				}
				bool beFlex = terminalConnType == 1;
				HYDuctConnect hyductConnect = new HYDuctConnect();
				int num = -1;
				if (string.IsNullOrEmpty(hyductConnect.CheckTerminalBeCovered(duct, terminal, ref num, false)) && (num == 22 || num == 33))
				{
					Duct piping;
					if (num == 22)
					{
						this.AlignTerminal(duct, terminal, alignType);
						piping = this.CreatHDuctAndConnTerminal(duct, terminal, beFlex);
					}
					else
					{
						this.MoveTerminalCenterToAlign(duct, terminal);
						piping = this.CreatHDuctAndConnTerminal(duct, terminal, beFlex);
					}
					YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(piping);
					Connector closeConnector = hypiping.GetCloseConnector(project, false);
					Connector closeConnector2 = hypiping2.GetCloseConnector(project, false);
					if (closeConnector != null && closeConnector2 != null && !closeConnector.IsConnected && !closeConnector2.IsConnected)
					{
						result = ((document.Create.NewElbowFitting(closeConnector, closeConnector2) == null) ? 0 : 1);
					}
				}
				else if (num == 33)
				{
					Duct turnDuct = this.GetTurnDuct(duct, terminal, beFlex);
					this.AlignDucts(duct, turnDuct, alignType);
					YJKPiping<Duct> hypiping3 = new YJKPiping<Duct>(turnDuct);
					Connector closeConnector3 = hypiping.GetCloseConnector(project, false);
					Connector closeConnector4 = hypiping3.GetCloseConnector(project, false);
					if (closeConnector3 != null && closeConnector4 != null && !closeConnector3.IsConnected && !closeConnector4.IsConnected)
					{
						result = ((document.Create.NewElbowFitting(closeConnector3, closeConnector4) == null) ? 0 : 1);
					}
				}
				subTransaction.Commit();
			}
			catch (Exception)
			{
				result = 0;
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return result;
		}

		private Duct FlexDuctConnection(Autodesk.Revit.DB.Document doc, Connector connector, YJKPiping<Duct> myDuct)
		{
			SubTransaction subTransaction = new SubTransaction(doc);
			Duct result;
			try
			{
				subTransaction.Start();
				double num = UnitConvert.CovertToAPI((double)this.LeadDuctLength, (Autodesk.Revit.DB.DisplayUnitType)2);
				XYZ startXYZ = connector.Origin + connector.CoordinateSystem.BasisZ * num;
				XYZ endXYZ = connector.Origin + connector.CoordinateSystem.BasisZ * num * 2.0;
				FlexDuctType flexDuctType = YJKRevitTools.GetContainNameElement(YJKElementFilter.GetElementByCategory(doc, BuiltInCategory.OST_FlexDuctCurves), YJKRevitTools.GetConnectorSharpName(connector)) as FlexDuctType;
				Duct duct = YJKRevitTools.NewDuct(myDuct.Piping, startXYZ, endXYZ);
				this.DuctSetParameter(connector, duct, false);
				Connector closeConnector = new YJKPiping<Duct>(duct).GetCloseConnector(connector.Origin, false);
				FlexDuct flexDuct = doc.Create.NewFlexDuct(connector, closeConnector, flexDuctType);
				this.SetFlexDuctByDuct(connector, flexDuct);
				doc.Regenerate();
				subTransaction.Commit();
				result = duct;
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				TransactionStatus status = subTransaction.GetStatus();
				if (subTransaction != null && 3 != (int)status)
				{
					subTransaction.RollBack();
				}
			}
			return result;
		}

		private void SetFlexDuctByDuct(Connector conn, FlexDuct flexDuct)
		{
			List<Connector> connectorAll = YJKRevitTools.GetConnectorAll(flexDuct);
			if (connectorAll != null && connectorAll.Count > 0 && connectorAll[0].Shape == conn.Shape)
			{
				foreach (Connector connector in connectorAll)
				{
					if (conn.Shape == ConnectorSharp.Rect || conn.Shape == ConnectorSharp.Oval)
					{
						connector.Width = conn.Width;
						connector.Height = conn.Height;
					}
					else if (conn.Shape == ConnectorSharp.Round)
					{
						connector.Radius = conn.Radius;
					}
				}
			}
		}

		public bool IsPerpendicular(XYZ vector1, XYZ vector2)
		{
			if (vector1 == XYZ.Zero || vector2 == XYZ.Zero)
			{
				return false;
			}
			double num = vector1.DotProduct(vector2);
			return num > -1E-09 && num < 1E-09;
		}

		private Duct CreatRDuctConnByArrowAlign(Duct duct, FamilyInstance terminal, int alignType, bool beFlex)
		{
			Duct duct2 = null;
			if (terminal == null || duct == null)
			{
				return duct2;
			}
			Autodesk.Revit.DB.Document document = duct.Document;
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
            Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
			double heightOrDiameter = hypiping.GetHeightOrDiameter();
			YJKLine hyline = new YJKLine(hypiping.StartConnector.Origin, hypiping.EndConnector.Origin);
			hyline.MakeUnBound();
			XYZ project = hyline.GetProject(elementConnector.Origin);
			XYZ xyz = new XYZ(project.X, project.Y, project.Z);
			if (alignType == 0)
			{
				xyz = new XYZ(xyz.X, xyz.Y, xyz.Z + heightOrDiameter / 2.0);
			}
			if (alignType == 2)
			{
				xyz = new XYZ(xyz.X, xyz.Y, xyz.Z - heightOrDiameter / 2.0);
			}
			if (beFlex)
			{
				double num = UnitConvert.CovertToAPI((double)this.LeadDuctLength, (Autodesk.Revit.DB.DisplayUnitType)2);
				XYZ startXYZ = elementConnector.Origin + elementConnector.CoordinateSystem.BasisZ * num;
				FlexDuctType flexDuctType = YJKRevitTools.GetContainNameElement(YJKElementFilter.GetElementByCategory(document, BuiltInCategory.OST_FlexDuctCurves), YJKRevitTools.GetConnectorSharpName(elementConnector)) as FlexDuctType;
				duct2 = YJKRevitTools.NewDuct(duct, startXYZ, xyz);
				this.DuctSetParameter(elementConnector, duct2, false);
				Connector closeConnector = new YJKPiping<Duct>(duct2).GetCloseConnector(elementConnector.Origin, false);
				FlexDuct flexDuct = document.Create.NewFlexDuct(elementConnector, closeConnector, flexDuctType);
				this.SetFlexDuctByDuct(elementConnector, flexDuct);
				document.Regenerate();
				hyrotateFamilyInstance.MovePiping(duct2);
			}
			else
			{
				duct2 = YJKRevitTools.NewDuct(duct, xyz, elementConnector.Origin);
				document.Regenerate();
				this.DuctSetParameter(elementConnector, duct2, false);
				hyrotateFamilyInstance.MovePiping(duct2);
				YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(duct2);
				if (hypiping2.BeRotateDuct(terminal))
				{
					hypiping2.Rotate90();
				}
				hypiping2.GetCloseConnector(elementConnector.Origin, false).ConnectTo(elementConnector);
				document.Regenerate();
			}
			return duct2;
		}

		private bool IsConnectableDistance(YJKPiping<Duct> hyDuct, FamilyInstance terminal, bool isAllCovered, bool isConnMore = false, float factor = 1.5f)
		{
			if (hyDuct == null || terminal == null)
			{
				return false;
			}
			double ductWidthorDiameter = YJKRevitTools.GetDuctWidthorDiameter(hyDuct.Piping);
			double ductHeightorDiameter = YJKRevitTools.GetDuctHeightorDiameter(hyDuct.Piping);
			Connector elementConnector = YJKRevitTools.GetElementConnector((Domain)1, terminal);
			YJKLine hyline = new YJKLine(hyDuct.StartConnector.Origin, hyDuct.EndConnector.Origin);
			hyline.MakeUnBound();
			XYZ project = hyline.GetProject(elementConnector.Origin);
			XYZ xyz = new XYZ(project.X, project.Y, elementConnector.Origin.Z);
			if (this.IsHorTerminal(terminal))
			{
				double num = xyz.DistanceTo(elementConnector.Origin);
				double num2 = xyz.DistanceTo(project);
				if (isAllCovered)
				{
					if (num2 > ductHeightorDiameter / 2.0 * (double)factor)
					{
						return true;
					}
				}
				else if (num > ductWidthorDiameter / 2.0 * (double)factor && num2 > ductHeightorDiameter / 2.0 * (double)factor)
				{
					return true;
				}
			}
			else
			{
				double num = xyz.DistanceTo(elementConnector.Origin);
				double num2 = xyz.DistanceTo(project);
				if (isAllCovered && num > ductWidthorDiameter / 2.0 * (double)factor)
				{
					return true;
				}
			}
			return false;
		}

		private int LeadDuctLength = 50;
	}
}
